﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "SimpleRunnable.generated.h"

/**	FRunnable
 *	概述
 *		UE4里，提供的多线程的方法：
 *			继承 FRunnable 接口创建单个线程
 *			创建 AsyncTask 调用线程池里面空闲的线程
 *			通过 TaskGraph 系统来异步完成一些自定义任务
 *		支持原生的多线程 std::thread
 *		在GameThread线程之外的其他线程中
 *			不要 spawning / modifying / deleting UObjects / AActors
 *			不要使用定时器 TimerManager
 *			不要使用任何绘制接口，例如 DrawDebugLine，然有可能崩溃
 *			如果想做的话，可以在主线程中异步处理
 *			其他线程中一般做数据收发和解析，数学运算等
 *	FRunnable
 *		FRunnable是UE4中多线程的实现方式之一，适用于复杂运算
 *		FRunnable 是线程的执行体，提供相应的接口。FRunnable需要依附与一个FRunnableThread对象，才能被执行
 *		FRunnable是UE4中多线程的实现方式之一，适用于复杂运算
 *		FRunnable 是线程的执行体，提供相应的接口。FRunnable需要依附与一个FRunnableThread对象，才能被执行
 *		FRunnableThread 表示一个可执行的线程，该类会派生出平台相关的子类。通过调用 FRunnableThread::Create 完成线程的创建
 *		class CORE_API FRunnable
 *		{
 *			public:
 *			virtual bool Init(); // 初始化 runnable 对象，在FRunnableThread创建线程对象后调用
 *			virtual uint32 Run() = 0; // Runnable 对象逻辑处理主体，在Init成功后调用
 *			virtual void Stop() {} // 停止 runnable 对象, 线程提前终止时被用户调用
 *			virtual void Exit() {} // 退出 runnable 对象，由FRunnableThread调用
 *		};
 */
class MISCELLANEOUSPROJECT_API FSimpleRunnable : public FRunnable
{
public:
	FSimpleRunnable(const FString& ThreadName);
	~FSimpleRunnable();
	void PauseThread(); // 线程挂起 方法一	
	void WakeUpThread(); // 线程唤醒 方法一
	void Suspend(bool bSuspend); // 线程挂起/唤醒 方法二
	void StopThread(); // 停止线程，一般用该方法
	void ShutDown(bool bShouldWait); // 停止线程，bShouldWait true的时候可强制 kill 线程

private:
	FString m_ThreadName;
	int32 m_ThreadID;
	bool bRun = true; // 线程循环标志
	bool bPause = false; //线程挂起标志
	FRunnableThread* ThreadIns; // 线程实例
	FEvent* ThreadEvent; //FEvent指针,挂起/激活线程, 在各自的线程内使用

	virtual bool Init() override;
	virtual uint32 Run() override;
	virtual void Stop() override;
	virtual void Exit() override;
};


UCLASS()
class MISCELLANEOUSPROJECT_API AThreadingTestActor : public AActor
{
	GENERATED_BODY()
protected:
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

private:
	FSimpleRunnable* SimpleRunnable;

public:
	UFUNCTION(BlueprintCallable)
	void CreateNewThread(const FString& ThreadName);

	UFUNCTION(BlueprintCallable)
	void PauseThread();

	UFUNCTION(BlueprintCallable)
	void SuspendThread(bool bSuspend);

	UFUNCTION(BlueprintCallable)
	void WakeUpThread();

	UFUNCTION(BlueprintCallable)
	void StopThread();

	UFUNCTION(BlueprintCallable)
	void ForceKillThread(bool bShouldWait);
};
